#ifndef _HELIX_MESH_H_
#define _HELIX_MESH_H_

#include "../../Helix.h"
#include "../../HObject.h"

#include <vector>
#include <map>
#include <string>


using namespace std;

namespace helix
{

	class MY_CLASS VertexArrayBuffer
	{
	public:
		vector<float> *buffer;	//the actual data that is stored (texture coordinates, vertex colors, etc...)
		int partsPerVertex;		//the number of float values that will be used for each vertex
		string name;			//an optional name for the vertex array buffer

		VertexArrayBuffer(float *data, int size, int partsPerVertex, const char *name="")
		{
			buffer = new vector<float>();
			for(int i=0;i<size;i++)
				buffer->push_back(data[i]);

			this->partsPerVertex = partsPerVertex;
			this->name = name;
		}

		virtual ~VertexArrayBuffer()
		{
			delete buffer;
		}
	};

	/**
	*	The Mesh class is responsible for holding all vertex and face data for a 3d mesh
	*	It consists of a buffer of face indices, a buffer of vertex indices, and any number of 
	*	extra predefined or custom per-vertex float buffers that carry extra information, like 
	*	texture coordinates and vertex colors.
	*/
	class MY_CLASS Mesh : public HObject
	{
	private:
		const static int VERTEX_BUFFER = 0;			//the index in the dataBuffers that corresponds to vertex data

		vector<int> bufferKeys;			//a list of all the attached buffers

		bool deleteDataBuffer(int bufferType);		//delete one of the attached buffers
		void addDataBuffer(int buffType, float *data, int partsPerVertex, const char *buffName);
		bool replaceDataBuffer(int bufferType, float *data);

		//Test whether two vertices are equal
		bool isSameVert(unsigned int currentIndex,unsigned int testIndex,vector< vector<float>* > newBuffers);

		map<int,VertexArrayBuffer*> dataBuffers;	//a map of vertex data buffers

		vector<unsigned int> *faceData;	//a vector of ints that define which vertices make up a face

		int faces;					//the number of faces in the mesh
		int verts;					//the number of vertices in the mesh
		int vertsPerFace;			//the number of vertices that are needed to create a face

		const static int CUSTOM_BUFFER_KEY_START = 1000;	//The first key value for a custom buffer 
		int customBuffers;


	public:
		/** This is a constant that tells the Mesh that each drawn element will consist of 1 vertex.
		*	ie. The entire mesh will be made up of points. */
		const static int POINT_MESH = 1;
		
		/** This is a constant that tells the Mesh that each drawn element will consist of 2 vertices. 
		*	ie. The entire mesh will be made up of lines. */
		const static int LINE_MESH = 2;
		
		/** This is a constant that tells the Mesh that each drawn element will consist of 3 vertices. 
		*	ie. The entire mesh will be made up of triangles. */ 
		const static int TRIANGLE_MESH = 3;
		
		/** This is a constant that tells the Mesh that each drawn element will consist of 4 vertices. 
		*	ie. The entire mesh will be made up of quads. */
		const static int QUAD_MESH = 4;

		/** A predefined vertex array buffer type that can hold one float value per mesh vertex  It is usually
		*	used for storing texture coordinate data.*/
		const static int TEX_COORD_1D_BUFFER = 1;

		/** A predefined vertex array buffer type that can hold two float values per mesh vertex.  It is usually
		*	used for storing texture coordinate data. */
		const static int TEX_COORD_2D_BUFFER = 2;
		
		/** A predefined vertex array buffer type that can hold three float values per mesh vertex.  It is usually
		*	used for storing texture coordinate data. */
		const static int TEX_COORD_3D_BUFFER = 3;
		
		/** A predefined vertex array buffer type that can hold three float values per mesh vertex.  It is usually
		*	used for storing rgb color data at each vertex. */
		const static int RGB_COLOR_BUFFER = 4;

		/** A predefined vertex array buffer type that can hold four float values per mesh vertex.  It is usually
		*	used for storing rgb color data at each vertex. */
		const static int RGBA_COLOR_BUFFER = 5;
		
		/** A predefined vertex array buffer type that can hold three float values per mesh vertex.  It is usually
		*	used for storing the surface normal at each vertex. */
		const static int NORMAL_BUFFER = 6;
		
		/** A predefined vertex array buffer type that can hold three float values per mesh vertex.  It is usually
		*	used for storing a vector that is tangent to the normal value and is aligned with the 2D texture
		*	coordinate space.  This is generally used in bumpmapping.  */
		const static int TANGENT_BUFFER = 7;
		
		/** A predefined vertex array buffer type that can hold three float values per mesh vertex.  It is usually
		*	used for storing a vector that is tangent to the normal and tangent values and is aligned with the 
		*	2D texture coordinate space.  This is generally used in bumpmapping.  */
		const static int BITANGENT_BUFFER = 8;


		/**	The only constructor creates a valid Mesh object.  Both source arrays will be coppied into the new Mesh object,
		*	so you can release them when you are done creating the object.
		*	\param vertsPerFace The number of vertices for each face in the Mesh (POINT_MESH, LINE_MESH, TRIANGLE_MESH, QUAD_MESH) 
		*	\param faceDataSize The size of the faceData array.
		*	\param faceIndexData The vertex index data that is used to create faces from a set of vertices.  For instance
		*	if vertsPerFace is 3, then the faceData array {1,2,3,2,3,4} will make two triangles.  The first with vertices
		*	1,2,and 3; and the second with vertices 2,3,and 4
		*	\param vertexDataSize The size of the vertexData array.
		*	\param vertexData The array of floats that corresponds with a 3D vertex.  For instance, the vertexData
		*	{1.0,1.0,1.0,3.0,3.0,3.0,-2.0,-3.0,0.0} would make 3 vertices.  The first at <1.0,1.0,1.0>, the second at
		*	<3.0,3.0,3.0>, and the third at <-2.0,-3.0,0.0>
		*/
		Mesh(int vertsPerFace, int faceDataSize, unsigned int* faceIndexData, int vertexDataSize, float* vertexData);

		/** Default deconstructor */
		virtual ~Mesh();


		/** Makes a copy of the float array and creates a new VertexArrayBuffer object for the named predefined bufferType
		*	If the specified bufferType has already been attached, this method will replace it with the new one
		*	\param data This is the float array that will be used to create the new VertexArrayBuffer object. The
		*	size of this array must equal the number of vertices in the mesh multiplied by the parts per vertex of the
		*	bufferType
		*	\param bufferType The type of predefined buffer to create.  Can be one of TEX_COORD_1D_BUFFER, TEXCOORD_2D_BUFFER
		*	TEX_COORD_3D_BUFFER, COLOR_BUFFER, NORMAL_BUFFER, TANGENT_BUFFER, or BITANGENT_BUFFER 
		*	\return true if the buffer was attached */
		bool attachDataBuffer(float *data, int bufferType);

		/** Makes a copy of the float array and creates a new VertexArrayBuffer object for a custom buffer
		*	\param data This is the float array that will be used to create the new VertexArrayBuffer object. The
		*	size of this array must equal the number of vertices in the mesh multiplied by the partsPerVertex
		*	\param partsPerVertex The number of float values that will be stored for each vertex (must be greater than 0)
		*	\buffName A string that can be used to store additional information about the buffer.
		*	\return An integer value used to identify the newly created buffer object, return -1 on error*/
		int attachCustomDataBuffer(float *data, int partsPerVertex, const char *buffName);

		/**This removes an attached buffer from the Mesh.  
		*	\param bufferType can either be a predefined buffer type, or a customDataBuffer ID 
		*	\return true if the buffer was detached, false if the specified buffer did not exist*/
		bool detachDataBuffer(int bufferType);

		/** Used to determine if a particular vertexBuffer object has been attached
		*	\param bufferType can either be a predefined buffer type, or a customDataBuffer ID 
		*	\return true if the buffer has been attached*/
		bool isBufferAvailable(int bufferType);         

		/** This is a method that removes all redundant vertex data.  This will reduce the total amount of data
		*	that a mesh needs to store.  This is mostly useded to create a normalized mesh after using a mesh
		*	editing tool. */
		void shareVerts();

		/** This is a method that removes all shared vertex data.  It creates unique vertices for all face data
		*	which means it can substantially increase memory usage on model with a lot of faces.  This is mainly
		*	used in conjunction with other mesh editing tools. */
		void unShareVerts();

		/**	Gets the number of vertices that make up a face
		*	\return The number of vertices used to create each face.  Will be >0 and will most likely be 4 or less. */
		int getVertsPerFace();

		/**	Gets the number of vertices 
		*	\return The number of vertices in the mesh */
		int getNumberOfVerts();

		/**	Gets the number of faces
		*	\return The number of faces in the mesh.*/
		int getNumberOfFaces();


		/** Get the number of elements (float values) per vertex for the specified buffer
		*	\param bufferType can either be a predefined buffer type, or a customDataBuffer ID 
		*	\return the number of elements (float values) per vertex for the buffer */
		int getElementsPerVertex(int bufferType);

		/** Get the vector<float> container for the specified bufferType
		*	\param bufferType can either be a predefined buffer type, or a customDataBuffer ID 
		*	\return The specified array of float values, returns null if it doesn't exist*/
		vector<float> *getData(int bufferType);

		/** Get the raw float array based on the specified bufferType
		*	\param bufferType can either be a predefined buffer type, or a customDataBuffer ID 
		*	\return The specified array of float values, returns null if it doesn't exist*/
		float *getRawDataBuffer(int bufferType);

		/** Get the vector<int> container for the face data
		*	\return a vector<int> container of face int values*/
		vector<unsigned int> *getFaceData();

		/**	Get the raw int array of vertex indices that correspond to each face
		*	\return the face data array */
		unsigned int *getRawFaceDataBuffer();				

		/** Get the vector<float> container for the vertex data
		*	\return a vector<float> container of vertex float values*/
		vector<float> *getVertData();

		/**	Get the raw float array of vertex data
		*	\return the vertex data array */
		float *getRawVertDataBuffer();

/*These probably need to be moved to a helper class of some kind
		bool ConvertOBJToHMF(char* OBJName,char *HMFName,bool solid);  //converts a .obj file to a .hmf file
		bool LoadFromHMF(char *fileName);                     //loads mesh data from a file
		bool SaveAsHMF(char *HMFName);			//saves the triangle mesh to a file

*/

		//virtual void Print();
	};

}

#endif

